import UIKit
import UserNotifications
import AVFoundation

class HomeViewController: UIViewController {

    @IBOutlet weak var connectionHintView: ConnectionHintView!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var guideView: UIView!
    @IBOutlet weak var bottomNavView: UIView!
    @IBOutlet weak var bottomNavConstraint: NSLayoutConstraint!

    private var dataSource: ConversationListDataSource!
    
    private var needRefresh = true
    private var refreshing = false
    private var currentOffset: CGFloat = 0
    
    private lazy var deleteAction = UITableViewRowAction(style: .destructive, title: Localized.MENU_DELETE, handler: tableViewCommitDeleteAction)
    private lazy var pinAction = UITableViewRowAction(style: .normal, title: Localized.HOME_CELL_ACTION_PIN, handler: tableViewCommitPinAction)
    private lazy var unpinAction = UITableViewRowAction(style: .normal, title: Localized.HOME_CELL_ACTION_UNPIN, handler: tableViewCommitPinAction)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        dataSource = ConversationListDataSource(tableView: self.tableView)
        
        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(UINib(nibName: "ConversationCell", bundle: nil), forCellReuseIdentifier: ConversationCell.cellIdentifier)
        tableView.separatorStyle = .singleLine
        tableView.tableFooterView = UIView()
        NotificationCenter.default.addObserver(self, selector: #selector(dataDidChange(_:)), name: .ConversationDidChange, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(dataDidChange(_:)), name: .UserDidChange, object: nil)
        
        connectionHintView.delegate = self
        ToxManager.shared.toxMananger!.user.delegate = self
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        if needRefresh {
            fetchConversations()
        }
        showBottomNav()
    }

    private func fetchConversations() {

    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }


    @IBAction func cameraAction(_ sender: Any) {
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            navigationController?.pushViewController(CameraViewController.instance(), animated: true)
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video, completionHandler: { [weak self](granted) in
                guard granted else {
                    return
                }
                DispatchQueue.main.async {
                    self?.navigationController?.pushViewController(CameraViewController.instance(), animated: true)
                }
            })
        case .denied, .restricted:
            alertSettings(Localized.PERMISSION_DENIED_CAMERA)
        }
    }

    @objc func dataDidChange(_ sender: Notification) {
        guard view?.isVisibleInScreen ?? false else {
            needRefresh = true
            return
        }
        guard !refreshing else {
            needRefresh = true
            return
        }
        fetchConversations()
    }
    
    @IBAction func contactsAction(_ sender: Any) {
        navigationController?.pushViewController(ContactViewController.instance(), animated: true)
    }

    class func instance() -> UIViewController {
        return Storyboard.home.instantiateInitialViewController()!
    }
    
}

extension HomeViewController: OCTSubmanagerUserDelegate {
    func submanagerUser(_ submanager: OCTSubmanagerUser, connectionStatusUpdate connectionStatus: OCTToxConnectionStatus) {
        let isOffline = (connectionStatus == .none)
        NotificationCenter.default.postOnMain(name: .SocketStatusChanged, object: !isOffline)
    }
}

extension HomeViewController: UITableViewDataSource, UITableViewDelegate {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.chats.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: ConversationCell.cellIdentifier) as! ConversationCell
        let chat = dataSource.chats[indexPath.row]
        cell.render(item: ConversationItem.create(by: chat))
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        let chat = dataSource.chats[indexPath.row]
        let item = ConversationItem.create(by: chat)
        item.unseenMessageCount = 0
        navigationController?.pushViewController(ConversationViewController.instance(conversation: item), animated: true)
    }

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let chat = dataSource.chats[indexPath.row]
        let conversation = ConversationItem.create(by: chat)
        if conversation.pinTime == nil {
            return [deleteAction, pinAction]
        } else {
            return [deleteAction, unpinAction]
        }
    }

    private func tableViewCommitPinAction(action: UITableViewRowAction, indexPath: IndexPath) {
        let chat = dataSource.chats[indexPath.row]
        let conversation = ConversationItem.create(by: chat)

        let destinationIndex: Int
        if conversation.pinTime == nil {
            let pinTime = Date().toUTCString()
            conversation.pinTime = pinTime
            destinationIndex = 0
        } else {
            conversation.pinTime = nil
        }
    }
    
    private func tableViewCommitDeleteAction(action: UITableViewRowAction, indexPath: IndexPath) {
        let chat = dataSource.chats[indexPath.row]
        let conversation = ConversationItem.create(by: chat)

        let alc = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
        if conversation.category == ConversationCategory.CONTACT.rawValue {
            alc.addAction(UIAlertAction(title: Localized.GROUP_MENU_DELETE, style: .destructive, handler: { [weak self](action) in
                self?.deleteAction(indexPath: indexPath)
            }))
        } else {
            alc.addAction(UIAlertAction(title: Localized.GROUP_MENU_CLEAR, style: .default, handler: { [weak self](action) in
                self?.clearChatAction(indexPath: indexPath)
            }))
        }
        if conversation.category == ConversationCategory.GROUP.rawValue {
            alc.addAction(UIAlertAction(title: Localized.GROUP_MENU_EXIT, style: .destructive, handler: { [weak self](action) in
                self?.deleteAndExitAction(indexPath: indexPath)
            }))
        }
        alc.addAction(UIAlertAction(title: Localized.DIALOG_BUTTON_CANCEL, style: .cancel, handler: nil))
        self.present(alc, animated: true, completion: nil)
        tableView.setEditing(false, animated: true)
    }

    private func clearChatAction(indexPath: IndexPath) {
    }

    private func deleteAction(indexPath: IndexPath) {
    }

    private func deleteAndExitAction(indexPath: IndexPath) {
    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        currentOffset = scrollView.contentOffset.y
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard abs(scrollView.contentOffset.y - currentOffset) > 10 else {
            return
        }

        if scrollView.contentOffset.y > currentOffset {
            hideBottomNav()
        } else {
            showBottomNav()
        }
    }

    private func hideBottomNav() {
        guard bottomNavView.alpha != 0 else {
            return
        }
        UIView.animate(withDuration: 0.25, delay: 0, options: [.showHideTransitionViews, .beginFromCurrentState], animations: {
            self.bottomNavView.alpha = 0
            self.bottomNavConstraint.constant = -122
            self.view.layoutIfNeeded()
        }, completion: nil)
    }

    private func showBottomNav() {
        guard bottomNavView.alpha != 1 else {
            return
        }
        UIView.animate(withDuration: 0.25, delay: 0, options: [.showHideTransitionViews, .beginFromCurrentState], animations: {
            self.bottomNavView.alpha = 1
            self.bottomNavConstraint.constant = 0
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

// MARK: - ConnectionHintViewDelegate
extension HomeViewController: ConnectionHintViewDelegate {
    
    func animateAlongsideConnectionHintView(_ view: ConnectionHintView, changingHeightWithDifference heightDifference: CGFloat) {
        tableView.contentOffset.y += heightDifference
    }
}

extension HomeViewController {

    private func checkUser() {
        
    }

    private func checkNotificationAuthorizationStatus() {
        UNUserNotificationCenter.current().checkNotificationSettings { (authorizationStatus: UNAuthorizationStatus) in
            switch authorizationStatus {
            case .authorized, .notDetermined:
                UNUserNotificationCenter.current().registerForRemoteNotifications()
            case .denied:
                break
            }
        }
    }
    
}
